﻿using System.ServiceModel.DomainServices.Server;
using Microsoft.Practices.Unity;
using System;
using AbstraX.ServerInterfaces;
using SolutionFramework.Entities;
using AbstraX.AssemblyInterfaces;
using AbstraX.Contracts;
using log4net;
using System.Collections.Generic;
using System.Linq;
using AbstraX.QueryProviders;

namespace SolutionFramework.Web
{
    public class DomainServiceFactory : IDomainServiceFactory
    {
        private IUnityContainer container = null;
        private Dictionary<Type, DomainService> services;

        public DomainServiceFactory(IUnityContainer container)
        {
            if (container == null)
            {
                throw new ArgumentNullException("unityContainer");
            }

            services = new Dictionary<Type, DomainService>();

            this.container = container;
        }

        public DomainService CreateDomainService(Type type, DomainServiceContext context)
        {
            var service = container.Resolve(type) as DomainService;

            if (context != null)
            {
                service.Initialize(context);
            }

            if (service is IAssemblyProviderService)
            {
                Global.DomainServiceHostApplication.AssemblyProviderService = (IAssemblyProviderService) service;
            }

            if (service is IAbstraXService)
            {
                var abstraXService = (IAbstraXService)service;

                abstraXService.DomainServiceHostApplication = Global.DomainServiceHostApplication;
            }

            if (service is IBindingsTreeService)
            {
                var bindingsTreeService = (IBindingsTreeService)service;

                bindingsTreeService.DomainServiceHostApplication = Global.DomainServiceHostApplication;
            }

            if (service is IEventsService)
            {
                var eventsService = (IEventsService)service;

                Global.DomainServiceHostApplication.EventsService = eventsService;
            }

            if (service is IAbstraXProviderService)
            {
                var abstraXProviderService = (IAbstraXProviderService) service;
                var rootID = abstraXProviderService.GetRootID();

                if (!Global.DomainServiceHostApplication.RegisteredServices.ContainsKey(rootID))
                {
                    Global.DomainServiceHostApplication.RegisteredServices.Add(rootID, abstraXProviderService);
                }
            }

            if (services.ContainsKey(type))
            {
                services.Remove(type);
            }

            services.Add(type, service);

            return service;
        }

        public void ReleaseDomainService(DomainService service)
        {
            service.Dispose();
            services.Remove(service.GetType());
        }

        public void Shutdown()
        {
            services.Values.ToList<DomainService>().ForEach(s => ReleaseDomainService(s));
            CachableQueryProvider.ShutdownCache();
        }
    }
}
